/*
 * MarkerUnifier_test.cpp
 *
 *  Created on: 4 gru 2013
 *      Author: dawid.wysakowicz
 */

#include "MarkerUnifier.hpp"
#include "gtest_wrapper.hpp"
#include <algorithm>

namespace ar
{
namespace utils
{

TEST(MarkerUnifier, twoPeopleOneAllelDoubled)
{
	dna::marker locus;
	locus.push_back(dna::allel('A'));
	locus.push_back(dna::allel('B'));
	locus.push_back(dna::allel('C'));

	MarkerUnifier unifier(2);

	std::list<dna::marker> markers = unifier.unify(locus);
	ASSERT_EQ(3, markers.size())<< "wrong markers count!";

	const char* results[] = { "ABCC", "ABBC", "AABC"};
	size_t i = 0;
	std::for_each(markers.begin(), markers.end(),
			[&i, &results] (const dna::marker& oneMarker)
			{
				std::stringstream str;
				std::for_each(oneMarker.begin(), oneMarker.end(),
						[&str](const dna::allel& variant)
						{
							str << variant;
						});
				EXPECT_STREQ(results[i++], str.str().c_str()) << "Bad results: " << str.str() << " on position " << i;
			});
}

TEST(MarkerUnifier, twoPeopleTwoAllelDoubled)
{
	dna::marker locus;
	locus.push_back(dna::allel('A'));
	locus.push_back(dna::allel('B'));

	MarkerUnifier unifier(2);

	std::list<dna::marker> markers = unifier.unify(locus);
	ASSERT_EQ(3, markers.size())<< "wrong markers count!";

	const char* results[] = {"ABBB", "AABB", "AAAB"};
	size_t i = 0;
	std::for_each(markers.begin(), markers.end(),
			[&i, &results] (const dna::marker& oneMarker)
			{
				std::stringstream str;
				std::for_each(oneMarker.begin(), oneMarker.end(),
						[&str](const dna::allel& variant)
						{
							str << variant;
						});
				EXPECT_STREQ(results[i++], str.str().c_str()) << "Bad results: " << str.str() << " on position " << i;
			});
}

TEST(MarkerUnifier, threePeopleOneAllelDoubled)
{
	dna::marker locus;
	locus.push_back(dna::allel('A'));
	locus.push_back(dna::allel('B'));
	locus.push_back(dna::allel('C'));
	locus.push_back(dna::allel('D'));
	locus.push_back(dna::allel('E'));

	MarkerUnifier unifier(3);

	std::list<dna::marker> markers = unifier.unify(locus);
	ASSERT_EQ(5, markers.size())<< "wrong markers count!";

	const char* results[] = { "ABCDEE", "ABCDDE", "ABCCDE", "ABBCDE", "AABCDE" };
	size_t i = 0;
	std::for_each(markers.begin(), markers.end(),
			[&i, &results] (const dna::marker& oneMarker)
			{
				std::stringstream str;
				std::for_each(oneMarker.begin(), oneMarker.end(),
						[&str](const dna::allel& variant)
						{
							str << variant;
						});
				EXPECT_STREQ(results[i++], str.str().c_str()) << "Bad results: " << str.str() << " on position " << i;
			});
}

TEST(MarkerUnifier, twoPeopleNoAllelsDoubled)
{
	dna::marker locus;
	locus.push_back(dna::allel('A'));
	locus.push_back(dna::allel('B'));
	locus.push_back(dna::allel('C'));
	locus.push_back(dna::allel('D'));

	MarkerUnifier unifier(2);

	std::list<dna::marker> markers = unifier.unify(locus);
	ASSERT_EQ(1, markers.size())<< "wrong markers count!";

	const char* results[] = { "ABCD" };
	size_t i = 0;
	std::for_each(markers.begin(), markers.end(),
			[&i, &results] (const dna::marker& oneMarker)
			{
				std::stringstream str;
				std::for_each(oneMarker.begin(), oneMarker.end(),
						[&str](const dna::allel& variant)
						{
							str << variant;
						});
				EXPECT_STREQ(results[i++], str.str().c_str()) << "Bad results: " << str.str() << " on position " << i;
			});
}

TEST(MarkerUnifier, twoPeopleNoAllelsDoubledShouldSort)
{
	dna::marker locus;
	locus.push_back(dna::allel('B'));
	locus.push_back(dna::allel('A'));
	locus.push_back(dna::allel('D'));
	locus.push_back(dna::allel('C'));

	MarkerUnifier unifier(2);

	std::list<dna::marker> markers = unifier.unify(locus);
	ASSERT_EQ(1, markers.size())<< "wrong markers count!";

	const char* results[] = { "ABCD" };
	size_t i = 0;
	std::for_each(markers.begin(), markers.end(),
			[&i, &results] (const dna::marker& oneMarker)
			{
				std::stringstream str;
				std::for_each(oneMarker.begin(), oneMarker.end(),
						[&str](const dna::allel& variant)
						{
							str << variant;
						});
				EXPECT_STREQ(results[i++], str.str().c_str()) << "Bad results: " << str.str() << " on position " << i;
			});
}

} /* namespace utils */
} /* namespace ar */
